<!--地图页面 -->
<template>
    <div class="map-frame-main">
      <!--  地图显示组件, id 必须是 map-->
      <div id="map" ref="map" :style="{backgroud: '#000000'}"></div>
      <MsgPopupForm ref="msgForm" :devData="devDataInfo" @close="popupClose"></MsgPopupForm>

      <Modal width="500px" v-model="showSelectDevices" @on-visible-change="onModalVisible">
        <DeviceSelectPopupForm ref="deviceSelectPopupForm" :devices="interCoordDevices"/>
      </Modal>

      <!-- 右菜单 -->
      <div ref="rightDiv" class="mf-right-div" v-show="showMenuTools">
          <MenuToolRight @mapMenuclick="genMap"
                          @centerClick="tocenter"
                          @fullscreenclick="fullCcreenClick"
                          :fullScrTitle="fullScreen.title"
                          @map-geom-tool-click="mapGeomToolClick"
                          ref="menuToolRight"
          />
      </div>
      <div class="mf-tool-div—top" v-show="showFenceTools">
        <MenuToolTop/>
      </div>
      <PaintTools ref="paintTools" />
    </div>

</template>
<script>
import LayerVector from "ol/layer/Vector.js";
import SourceVector from "ol/source/Vector.js";
import {Map, View} from "ol";
import {polygonStyle,pointStyle,focusPointStyle} from './maptools/tool/style'
import Feature from 'ol/Feature.js';
import Point from 'ol/geom/Point.js';
import Overlay from "ol/Overlay";
import {Cluster, OSM, Vector as VectorSource} from 'ol/source.js';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer.js';
import MapTools from "./maptools/MapTools";
import {genSource,commLayer,commView} from './maptools/MapSource.js';
import {Circle as CircleStyle,Fill,Stroke,Style,Text,Icon} from 'ol/style.js';
import DrawerLeftButton from "@/view/Home/component/DrawerLeftButton";
import DrawerLeft from "@/view/Home/component/DrawerLeft";
import GbDevicetree from "_c/topnav/GbDeviceTree";
import Ranging from "@/view/Home/map/maptools/tool/Ranging";
import MsgPopupForm from "@/view/Home/map/MsgPopupForm";
import Position from '@/api/position';
import MenuTools1 from "@/view/Home/map/site/MenuTools";

import MenuToolRight from "@/view/Home/map/site/MenuToolRight";
import MenuToolTop from "@/view/Home/map/site/MenuToolTop";

import {exitFullScreen, setFullScreen} from "@/view/Home/HomeCommFunction";
import MapCenterInfo from "@/api/mapinfo";
import MapInfo from "@/view/Home/map/maptools/data/MapInfo";
import PaintTools from "@/view/Home/map/maptools/tool/PaintTools";
import DeviceSelectPopupForm from "@/view/Home/map/DeviceSelectPopupForm";
export default {
  name:"Mapframe",
  components:{DeviceSelectPopupForm,MapTools,DrawerLeftButton,DrawerLeft,GbDevicetree,MenuTools1,MenuToolRight,MsgPopupForm,PaintTools,MenuToolTop},
  props:{
    deviceData:{
      type:Array,
      default () {
        return []
      },
    },
    showMenuTools: {
      type:Boolean,
      default() {
        return true
      }
    },
    showFenceTools: {
      type:Boolean,
      default() {
        return false
      }
    }

  },
  watch:{
    deviceData(){
      //console.log(">>>>>> MapFrame.deviceData:%o",this.deviceData);
    }
  },
  computed:{
    drawerLeftDisplay(){
      return this.drawerLeft.display;
    },
    drawerLeftBtnDisplay(){
      return this.drawerLeft.display;
    },
  },
  data() {
    return {
      deviceInfoList:[], //设备数据，由方法refreshCluser的参数 传入，保存在这里，在设备定位时，把要定位的设备放到最后一个，然后重新画，就可以实现当前选中的设备在最上层了
      showSelectDevices:false,
      currentLevel:11, //当前地图级别
      currentMapSource:"ArcGis", //当前地图源
      currentMapType:this.$t('map_type_image'), //当前地图类型

      customLayers:{
        /**layer：层
         contorl：控件
         feature：元素
         interaction：交互
         Vector：矢量的
         Tile：瓦片
         source：资源
         format：转换
         projection：投影
         */
        layerVector: new LayerVector(),
        sourceVector: new SourceVector(),
      },
      clusters:null,
      clusterStyles:{}, //汇聚数据对象
      currentItem:null,
      canSimuPos:false, //允许摸拟定位信息上报，false 关闭此功能
      devDataInfo: {
        title: "",
        arrt: {
          channelCode: "",
          deviceName: "",
          userName: "",
          longitude: "0",
          latitude: "0",
          direction: "",
          speed: "10KM/S",
          locate: "",
          orgName: ""
        },
      },
      devicesPoints:[],
      interCoordDevices:[], //在框内的设备
      drawing:{
        drawing:false,
        name:this.$t('end')
      },
      drawerLeft:{
        drawerHeight:'60%',
        drawerWidth:'300px',
        inner:false,
        display: false,
        mask: false,
      },
      elementId: 'map',
      fullScreen:{
        isFull:false,
        title:this.$t('map_tool_full_screen')
      },
      iszooming:false, //正在缩放中
      mapApi: new MapCenterInfo(),
      mapData:null,
      msgTitle:"map popup window",
      mapInfo:null,
      mapObj:null,
      mapEventFun:{
        singleclickEvent:null, //鼠标单击事件
        dblclickEvent:null, //鼠标双击事件
        pointermoveEvent:null, //移动鼠标取得定位事件
        mapZoom: { //放大缩小事件
          mapZoomEvent:null,//事件
          registerOnZoom:null,//注册事件
          removeZoomRegister:null,//移除事件注册
        },
        msgPopupForm:null, //弹窗
      },
      posGroup:[],
      posApi: new Position(),
      ranging: new Ranging(), //是否正在测距
      simulState:false, //正在摸拟定位信息
    }
  },
  created() {

  },
  mounted() {
    /** 取得默认的地图信息 */
    this.mapInfo = new MapInfo().get();
    //console.log(">>>>>>> Mapframe.mounted: mapinfo=%o",this.mapInfo);
    this.$nextTick(()=>{
      this.init();
    });


    //console.log(">>>>>>> Mapframe.mounted: 测试gcj02ToGps84");
    //new Gps().gcj02ToGps84(29.550650375976563,106.47912282006837 );
  },
  methods: {

    /**
     * 画图
     */
    draw(type) {
      const that=this;

      if (type === "Clear"){
        this.$refs.paintTools.clear();
        /*结束测距*/
        this.ranging.finish();

      }else  if (type === "Distance"){
        /*开始测距 */
        this.ranging.setMap(this.mapObj);
        this.ranging.setLayer(this.customLayers.layerVector);
        this.ranging.setSource(this.customLayers.sourceVector);
        this.ranging.start();
      }else{
        //画各种图
        this.$refs.paintTools.clear(); //防止形状叠加
        this.$refs.paintTools.startDraw(this.mapObj,this.customLayers.sourceVector,type,(feature)=>{
          const geometry = feature.getGeometry();
          this.interCoordDevices = [];
          for(let j in this.devicesPoints){
            //设备是否在框选的范围内
            const deviceInfo = this.devicesPoints[j].get("deviceInfo");
            if (geometry.intersectsCoordinate([deviceInfo.longitude,deviceInfo.latitude])){
              this.interCoordDevices.push(deviceInfo);
            }
          }
          //框选弹窗
          if (this.interCoordDevices.length > 0){
            this.showSelectDevices = true;
          }else{
            this.$Message.error(this.$t('no_select_data'));//"=====没有被选中的设备======");
            //console.log(">>>>>>>>>>> Mapframge.start: 延时清理");
            setTimeout(function () {
              //console.log("延时清理一次,不延时删除不掉最后一个")
              that.$refs.paintTools.clear();
            }, 2000);
          }


        });
      }
    },
    drawend(type) {
      if (type == "DISTANCE") {
        /*结束测距*/
        this.ranging.finish();
      }
    },
    drawerLeftBtnClick(show) {
      /** 左边抽屉按钮点击 */
      this.drawerLeft.display = show;
    },
    drawerLeftClick() {
      /* 点击关闭按钮 */
      this.drawerLeft.display = false;
    },







    /**
     * 传递地图信息
     */
    emitMapInfo(){
      let level=!!this.currentLevel?this.currentLevel.toFixed(1):0;
      const event = "《" + this.currentMapSource + " " + this.currentMapType +"》，level：" + level;
      this.$emit('mapInfoEvent', event);
    },


    /**
     * 点周全屏按钮
     */
    fullCcreenClick(){
      if (this.fullScreen.isFull){
        exitFullScreen();
        this.fullScreen.isFull = false;
        this.fullScreen.title = this.$t('map_tool_full_screen');
      }else{
        setFullScreen();
        this.fullScreen.isFull = true;
        this.fullScreen.title = this.$t('map_tool_exit_full_screen');
      }
    },
    /**
     * 生成 地图
     */
    genMap(mapSubData) {
      console.log("!!!!!!!! Mapframe.genMap: mapData :%o",mapSubData);
      if (!!mapSubData){
        this.mapData = mapSubData;
        //console.log("!!!!!!!! Mapframe.genMap: mapData 没有赋值！");
        //return;
      }
      //console.log(">>>>>>>>>>>>> Mapframe.genMap: subData=%o",subData);
      if (!!this.mapObj){
        //已经存在的地图则移除事件图层等
        if (!!this.mapEventFun.singleclickEvent){
          this.mapObj.un("singleclick",this.mapEventFun.singleclickEvent);
        }
        //鼠标双击事件
        if (!!this.mapEventFun.dblclickEvent){
          this.mapObj.un("dblclick",this.mapEventFun.dblclickEvent);
        }
        //鼠标移动事件
        if (!!this.mapEventFun.pointermoveEvent){
          this.mapObj.un("pointermove",this.mapEventFun.pointermoveEvent);
        }
        //地图放大事件
        if (!!this.mapEventFun.mapZoomEvent){
          //this.mapObj.un("moveend",this.mapEventFun.mapZoomEvent);
          this.mapEventFun.mapZoom.removeZoomRegister();
        }
        //弹窗事件
        if (!!this.mapEventFun.msgPopupForm){
          this.mapObj.removeLayer(this.mapEventFun.msgPopupForm)
        }

      }

      //产生新的地图
      let subData={};
      subData.name = this.mapInfo.mapName;
      subData.type = this.mapInfo.mapType;
      subData.url = this.mapInfo.sub.url;
      subData.minZoom = this.mapInfo.minZoom;
      subData.maxZoom = this.mapInfo.minZoom;
      //console.log("!!!!!!! Mapframe.elementId: %o",this.elementId);
      this.mapObj = genSource(this.elementId, this.mapObj, subData);
      //console.log("!!!!!!! Mapframe.mapObj: %o",this.mapObj);
      const that = this;
      this.$nextTick(()=>{
        if (!that.mapObj){
          that.$Message.error(this.$t('map_load_fail_casuse'));
            return;
        }
        //给地图强化，加事件，弹窗等
        this.genMapEventFuns();
      });

      this.mapObj.addLayer(this.customLayers.layerVector);

/*
      if (!!this.mapData.map) {
        this.currentItem = this.mapData.map;
        this.mapObj.addLayer(this.customLayers.layerVector);
        this.currentMapSource = this.mapData.mapName;
        this.currentMapType = this.mapData.mapType;
      }
*/

      this.emitMapInfo();
      //传递地图至上级
      this.$emit('afteGenMap', this.mapObj);

      if (!!this.mapObj){
        //console.log(">>>>>>>=== this.mapInfo.center",this.mapInfo.center);
        this.mapObj.getView().setCenter(this.mapInfo.center);
      }
    },

    /**
     *  地图鼠标事件处理
     *  单击，双击，移动等
     */
    genMapEventFuns(){
      //单击事件
      let that = this;
      this.mapEventFun.singleclickEvent=(ev)=>{
        let pixel = ev.pixel   // 鼠标点击的位置，这个应该是像素
        let mouse = ev.coordinate  // 鼠标点击的坐标位置
        let feature = that.mapObj.forEachFeatureAtPixel(pixel, (feature) => {
          return feature   // 查找出点击的哪个坐标
        })

        if (feature) {  // 如果是点击了坐标点

          //这是判断是否点击了聚合图标
          const features = feature.get("features");
          //console.log(">>>>>>> Mapframe.genMapEventFuns: features:%o",this.features);
          if (!!features && features.length > 0){
            that.devDataInfo=features[0].get("deviceInfo");
            //console.log(">>>>>>> Mapframe.genMapEventFuns: deviceInfo:%o",this.devDataInfo);
            that.msgTitle="click to popup"  // 获取坐标点的数据
            that.mapEventFun.msgPopupForm.setPosition(mouse)  // 设置弹窗的位置
            return;
          }
          //普通的点
          that.devDataInfo=feature.get("deviceInfo");
          //console.log(">>>>>>> Mapframe.genMapEventFuns: deviceInfo:%o",this.devDataInfo);
          if (!!that.devDataInfo){
            that.msgTitle=this.$t('device_info')  // 获取坐标点的数据
            that.mapEventFun.msgPopupForm.setPosition(mouse)  // 设置弹窗的位置
          }


        } else {
          that.mapEventFun.msgPopupForm.setPosition(undefined)  // 如果没有点击坐标点，就隐藏弹窗
        }
      }
      this.mapObj.on('singleclick',this.mapEventFun.singleclickEvent);

      /**
       * 双击
       */
      this.mapEventFun.dblclickEvent=(evt)=>{
        //开启或关闭摸拟定位上传
        if (that.canSimuPos){
          that.simulState = !that.simulState;
          if (that.simulState){
            console.log("打开拾取GPS");
          }else{
            console.log("关闭拾取GPS");
          }
        }else{
          this.simulState = false;
        }
      }
      this.mapObj.on('dblclick', this.mapEventFun.dblclickEvent);

      //移动鼠标取得定位事件
      this.mapEventFun.pointermoveEvent=(evt)=>{
        const currentLocate = evt.coordinate[0] + "," + evt.coordinate[1];
        this.$emit('locateEvent', currentLocate);

        let centerPoint1={lat:evt.coordinate[1],lon:evt.coordinate[0]};
        if (this.simulState){
          //变为WGS84
          if (this.mapInfo.coordinateType == 'GCJ02'){
            //谷歌高德
            centerPoint1 = gps.gcj02ToGps84(parseFloat(evt.coordinate[1]), parseFloat(evt.coordinate[0]));
          }else if (this.mapInfo.coordinateType == 'BD09') {
            //百度
            centerPoint1 = gps.bd09ToGps84(parseFloat(evt.coordinate[1]), parseFloat(evt.coordinate[0]));
          }//WGS84 和其它 不变

          let pos = {
            longitude:centerPoint1[0],
            latitude:centerPoint1[1]
          }

          this.posGroup.push(pos);
          if (this.posGroup.length >= 10){
            const param = JSON.stringify(this.posGroup);
            this.posGroup=[];
            this.posApi.saveBatchPos(param).then(res => {
              //console.log("res.data:%o",res.data);
            })
          }
        }else{
          if (this.posGroup.length > 0){
            const param = JSON.stringify(this.posGroup);
            this.posGroup=[];
            this.posApi.saveBatchPos(param).then(res => {
              //console.log(">>>>>>>> Mapframe.genMapEventFuns.saveBatchPos: res.data:%o",res.data);
            })
          }
        }
      };
      this.mapObj.on('pointermove', this.mapEventFun.pointermoveEvent);


      //给地图加弹窗图层
      this.mapEventFun.msgPopupForm=new Overlay({ // 创建一个图层
        element: that.$refs.msgForm.$el,  // 图层绑定我们上边的弹窗
        /*autoPan: true,*/
        autoPan: false,
        autoPanAnimation: {duration: 250}
      });
      this.mapEventFun.msgPopupForm.setPosition(undefined); // 设置弹窗位置，刚开始我们不让他显示，就是undefined就行
      this.mapObj.addOverlay(this.mapEventFun.msgPopupForm)  // 然后把弹窗的图层加载到地图上

      /** 缩放监听事件 */
      /**
       * 地图缩放回调函数
       */
      this.mapEventFun.mapZoom.mapZoomEvent=(event)=>{
        that.iszooming=false; //缩放结束
        that.currentLevel = that.mapObj.getView().getZoom();
        that.emitMapInfo();
      };

      /**
       * 注册地图缩放和拖动事件方法
       * 第一个参数是监听事件，第二个参数为是否开启监听拖动（true为不开启）
       * @param eventListen
       * @param notListenMove
       */
      this.mapEventFun.mapZoom.registerOnZoom=(eventListen, notListenMove)=>{
        // 记录地图缩放，用于判断拖动
        let mapObj = that.mapObj;
        mapObj.lastZoom = mapObj.lastZoom || mapObj.getView().getZoom();
        // 地图缩放事件
        let registerOnZoom = function (e) {
          // 不监听地图拖动事件
          if (notListenMove) {
            if (mapObj.lastZoom != mapObj.getView().getZoom()) {
              eventListen && eventListen(e);
            }
          } else {
            eventListen && eventListen(e);
          }
          mapObj.lastZoom = mapObj.getView().getZoom();
        }
        // 保存缩放和拖动事件对象，用于后期移除
        let registerOnZoomArr = mapObj.get('registerOnZoom') || [];
        registerOnZoomArr.push(this.mapEventFun.mapZoom.registerOnZoom);
        // 使用地图 set 方法保存事件对象
        mapObj.set('registerOnZoom', registerOnZoomArr);
        // 监听地图移动结束事件
        mapObj.on('moveend', registerOnZoom);
        return eventListen;
      };

      /**
       * 移除缩放和拖动事件对象
       */
      this.mapEventFun.mapZoom.removeZoomRegister=()=>{
        let registerOnZoomArr = that.mapObj.get('registerOnZoom');
        if (registerOnZoomArr && registerOnZoomArr.length > 0) {
          for (let i = 0; i < registerOnZoomArr.length; i++) {
            that.mapObj.un('moveend', registerOnZoomArr[i]);
          }
        }
      }

      //注册地图缩放监听
      this.mapEventFun.mapZoom.registerOnZoom(this.mapEventFun.mapZoom.mapZoomEvent, true);

      /**
       mapEventFun:{
        singleclickEvent:null, //鼠标单击事件
        dblclickEvent:null, //鼠标双击事件
        pointermoveEvent:null, //移动鼠标取得定位事件
        mapZoomEvent:null, //放大缩小事件
        msgPopupForm:null, //弹窗
      }
       */


      //this.genMsgModel();
      /** 单击，弹出对应终端弹窗
       *  鼠标事件汇总
       *  singleclick:地图单击事件。
       dblclick:地图双击事件。
       click:地图点击事件。
       pointerdrag：鼠标拖拽事件。
       pointermove：鼠标移动事件。
       postcompose：地图渲染中。
       precompose:准备渲染，未渲染。
       postrender:渲染全部结束。
       地图移动事件
       moveend:地图移动结束发生，没什么好说的。
       复杂的change事件
       change:layerGroup :地图图层增删时触发。
       change:size :地图窗口发生变化就会触发，与我们常用的窗口resize接近。
       change:target :地图绑定的div发生更改时触发，如map.setTartget方法就会触发该事件。
       change:view :地图view对象发生变化触发。
       propertychange: Map对象中任意的property值改变时触发。
       change:博主也懂。
       View事件：moving，moveend，zoom，zoomend
       * */
      /*     this.mapObj.on('singleclick', (ev) => {
             let that = this;
             let pixel = ev.pixel   // 鼠标点击的位置，这个应该是像素
             let mouse = ev.coordinate  // 鼠标点击的坐标位置
             let feature = that.mapObj.forEachFeatureAtPixel(pixel, (feature) => {
               return feature   // 查找出点击的哪个坐标
             })

             if (feature) {  // 如果是点击了坐标点
               const features = feature.get("features");
               if (features.length > 1){
                 return;
               }

               this.devDataInfo=features[0].get("deviceInfo");
               console.log("deviceInfo:%o",this.devDataInfo);
               that.msgTitle="点出弹窗"  // 获取坐标点的数据
               that.overlayForm.setPosition(mouse)  // 设置弹窗的位置

             } else {
               that.overlayForm.setPosition(undefined)  // 如果没有点击坐标点，就隐藏弹窗
             }
           })*/



      /** 缩放监听事件 */
      //this.listenersZoom();

      /** 移动鼠标取得定位事件 */
      /**
       this.mapObj.on('pointermove',(evt)=>{
        this.currentLocate = evt.coordinate[0] + "," + evt.coordinate[1];
        this.$emit('locateEvent', this.currentLocate);

        let centerPoint1={lat:evt.coordinate[1],lon:evt.coordinate[0]};
        const gps = new GPS();
        if (this.simulState){
          //变为WGS84
          if (this.mapInfo.coordinateType == 'GCJ02'){
            //谷歌高德
            centerPoint1 = gps.gcj02ToGps84(parseFloat(evt.coordinate[1]), parseFloat(evt.coordinate[0]));
          }else if (this.mapInfo.coordinateType == 'BD09') {
            //百度
            centerPoint1 = gps.bd09ToGps84(parseFloat(evt.coordinate[1]), parseFloat(evt.coordinate[0]));
          }//WGS84 和其它 不变

          let pos = {
            longitude:centerPoint1[0],
            latitude:centerPoint1[1]
          }

          this.posGroup.push(pos);
          if (this.posGroup.length >= 10){
            const param = JSON.stringify(this.posGroup);
            this.posGroup=[];
            this.posApi.saveBatchPos(param).then(res => {
              console.log("res.data:%o",res.data);
            })
          }
        }else{
          if (this.posGroup.length > 0){
            const param = JSON.stringify(this.posGroup);
            this.posGroup=[];
            this.posApi.saveBatchPos(param).then(res => {
              console.log("res.data:%o",res.data);
            })
          }
        }
      });
       */
    },
    /**
     * 给地图添加弹窗图层
     */
    genMsgModel() {
      /*      this.overlayForm = new Overlay({ // 创建一个图层
              element: this.$refs.msgForm.$el,  // 图层绑定我们上边的弹窗
              /!*autoPan: true,*!/
              autoPan: false,
              autoPanAnimation: {duration: 250}
            });
            this.overlayForm.setPosition(undefined); // 设置弹窗位置，刚开始我们不让他显示，就是undefined就行
            this.mapObj.addOverlay(this.overlayForm)  // 然后把弹窗的图层加载到地图上*/
    },
    /**
     *
     * @param distance 要素将被聚合在一起的像素距离，默认为20
     * @param minDistance 聚合块之间的最小像素距离，默认为零
     */
    getRadomCluserLayer(distance, minDistance) {
      //
      let coord = null;
      const count = 50;
      const features = new Array(count);

      for (let i = 0; i < count; i++) { // 随机生成五百个点并添加至地图
        coord = [this.mapInfo.center[0] + Math.random() * 0.05, this.mapInfo.center[1] + Math.random() * 0.05];
        features[i] = new Feature({
          geometry: new Point(coord),
        });
      }

      const source = new VectorSource({
        features: features,
      });

      const clusterSource = new Cluster({
        distance: parseInt(distance, 10),
        minDistance: parseInt(minDistance, 10),
        source: source,
      });

      const styleCache = {};
      const clusters = new VectorLayer({
        source: clusterSource,
        style: function (feature) {
          const size = feature.get('features').length;
          let style = styleCache[size];
          if (!style) {
            if (size === 1) {
              style = new Style({
                image: new Icon({
                  src: 'images/marker_online.png'
                }),
                text: new Text({
                  text: "",
                  fill: new Fill({
                    color: '#fff',
                  }),
                }),
              })
            } else {
              if (size > 10) {
                style = new Style({
                  image: new CircleStyle({
                    radius: 20,
                    stroke: new Stroke({
                      color: '#fff',
                    }),
                    fill: new Fill({
                      color: 'red',
                    }),
                  }),
                  text: new Text({
                    text: size.toString(),
                    fill: new Fill({
                      color: '#fff',
                    }),
                  }),
                });
              } else if (size > 5) {
                style = new Style({
                  image: new CircleStyle({
                    radius: 20,
                    stroke: new Stroke({
                      color: '#fff',
                    }),
                    fill: new Fill({
                      color: 'green',
                    }),
                  }),
                  text: new Text({
                    text: size.toString(),
                    fill: new Fill({
                      color: '#fff',
                    }),
                  }),
                });
              } else {
                style = new Style({
                  image: new CircleStyle({
                    radius: 20,
                    stroke: new Stroke({
                      color: '#fff',
                    }),
                    fill: new Fill({
                      color: 'blue',
                    }),
                  }),
                  text: new Text({
                    text: size.toString(),
                    fill: new Fill({
                      color: '#fff',
                    }),
                  }),
                });
              }


            }
            styleCache[size] = style;
          }

          return style;
        },
      });

      //return clusters;
      //ArcgisYX': //Arcgis影像


      if (this.mapObj) {
        this.mapObj.addLayer(clusters);
      } else {
        const raster = commLayer('https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}');
        const view1 = commView();
        this.mapObj = new Map({
          layers: [raster, clusters],
          target: 'map',
          view: view1
          /*
                  view: new View({
                    center: [this.mapInfo.centerLonitude, this.mapInfo.centerLatitude],
                    zoom: this.mapInfo.defaultZomm,
                  }),
          */
        });
      }

    },
    //初始化
    init() {
      /** 生成画图的图层和资源 */
      this.customLayers.layerVector.setSource(this.customLayers.sourceVector);
      this.customLayers.layerVector.setStyle(polygonStyle);

      //const mi = this.mapInfo;
      //this.mapData = this.$refs.menuToolRight.changeMenu(mi.mapName, mi.mapType);

      this.genMap();
    },
    listenersZoom() {
      //console.log('开始监听缩放地图！');
      //注册事件
      //this.registerOnZoom(this.mapZoomEvent, true)
    },
    /**
     * 根据点击的点找到地图上该设备的位置
     */
    locate(devData){
      const that=this;
      //console.log("*********** Mapframe.locate: devData=%o",devData)
      if (!devData.longitude || !devData.latitude){
        //console.log("设备没有定位信息！");
        that.$Message.error(this.$t('device_no_location_data'));
        return;
      }else{
        //console.log(">>>>>>> Mapframe::locate: devicesPoints=%o",this.devicesPoints);
        //console.log(">>>>>>> Mapframe::locate: devicesPoints.length=%o",this.devicesPoints.length);
        if (!!!this.devicesPoints || this.devicesPoints.length === 0){
          this.drawOnePoint(devData,true);
          this.tocenter([devData.longitude,devData.latitude]);
          return;
        }
        //先移队所有的点
        for(let l in this.devicesPoints){
          this.customLayers.sourceVector.removeFeature(this.devicesPoints[l]);
        }
        this.devicesPoints=[];
        if (!!!this.deviceInfoList || this.deviceInfoList.length === 0){
          this.drawOnePoint(devData,true);
          this.tocenter([devData.longitude,devData.latitude]);
          return;
        }

        let deviceInfo = null;
        for(let i in this.deviceInfoList){
          if (this.deviceInfoList[i].id === devData.id) {
            deviceInfo = this.deviceInfoList[i];
          } else {
            this.drawOnePoint(this.deviceInfoList[i]);
          }
        }
        //选中的这个最后显示
        if (!!deviceInfo){this.drawOnePoint(deviceInfo,true);}
        this.tocenter([devData.longitude,devData.latitude]);
      }
      //寻找汇聚点
    },

    /**
     * 画单个点
     */
    drawOnePoint(deviceInfo,focus) {

      //只保留一个点
      let point = new Feature({
        geometry: new Point([deviceInfo.longitude,deviceInfo.latitude]),
        device:{lng:deviceInfo.longitude,lat:deviceInfo.latitude},
        deviceInfo: deviceInfo
      });
      if (!!focus){
        point.setStyle(focusPointStyle(deviceInfo));
      }else{
        point.setStyle(pointStyle(deviceInfo));
      }

      this.customLayers.sourceVector.addFeature(point);
      this.devicesPoints.push(point);
    },

    /**
     * 点周地图工具
     * name：line/直线，polygon/多边形，circle/园形，distance/测距，zoomin/放大，zoomout/缩小
     */
    mapGeomToolClick(name){
      if (name !=="Zoomin" && name!=="Zoomout"){
        this.draw(name);
      }else if (name==="Zoomin"){
        this.zoomin()
      }else if (name==="Zoomout"){
        this.zoomout();
      }

    },
    /**
     * 地图缩放回调函数
     */
    mapZoomEvent(event) {

    },
    onModalVisible(state){

      if (state == false)
        this.$refs.paintTools.clear();
    },
    /**
     * 点击波波上的按钮
     * @param event
     * @param node
     * @param data
     */
/*    popupBtnClick(event,node, data){
/!*      console.log("chnClick(event,node, data): ");
      console.log("event: %o ",event);
      console.log("node: %o ",node);
      console.log("data: %o ",data);
      console.log(">>>>>>>> [Mapframe]: popupBtnClick ");*!/
      this.$emit('popupBtnClick',event,node, data);
    },*/
    /**
     * 关闭波波
     */
    popupClose() {
      this.mapEventFun.msgPopupForm.setPosition(undefined);
    },



    /**
     * 根据设备数据刷汇聚点
     *
     * @param distance 要素将被聚合在一起的像素距离，默认为20
     * @param minDistance 聚合块之间的最小像素距离，默认为零
     * @param deviceData 设备数据
     */
    refreshCluser(distance, minDistance,deviceData) {
      if (!!!this.mapObj || !!!deviceData){
        return ;
      }
      //保存设备列表数据
      this.deviceInfoList = deviceData;

      if (!!this.clusters){
        this.mapObj.removeLayer(this.clusters);
      }

      let coord = null;
      const count = this.deviceInfoList.length;
      const features = new Array(count);

      let pos = null;
      for (let i = 0; i < count; i++) {
        //地图转换
        //coord = solveGps("WGS84",parseFloat(deviceData[i].latitude),parseFloat(deviceData[i].longitude));

        coord = new Object();
        coord.lng=this.deviceInfoList[i].longitude;
        coord.lat=this.deviceInfoList[i].latitude;

        features[i] = new Feature({
          geometry: new Point(coord),
          deviceInfo: this.deviceInfoList[i]
        });
      }
      //console.log(">>>>>>>>>>>> Mapframe.refreshCluser;=================");
      const source = new VectorSource({features: features});
      const clusterSource = new Cluster({
        distance: parseInt(distance, 0),
        minDistance: parseInt(minDistance, 0),
        source: source,
      });
      this.clusterStyles = {};
      const that=this;

      this.clusters = new VectorLayer({
        source: clusterSource,
        style: function (feature) {

          const features = feature.get('features');
          const size = features.length;
          if (size > 1){
            for(let i=size-1;i>=0;i--){
              delete that.clusterStyles[features[i].get("deviceInfo").id];
            }
          }
          let deviceInfo=null;
          let id=null;
          if (size===1){
            deviceInfo = feature.get('features')[0].get("deviceInfo");
            id=deviceInfo.id;
          }else{
            id=size;
          }
          let style = that.clusterStyles[id];
          if (!style) {
            if (size === 1) {
              style = new Style({
                image: new Icon({
                  src: deviceInfo.online=="0"?"images/marker_offline.png":"images/marker_online.png"
                }),
                text: new Text({
                  // 对其方式
                  textAlign: 'center',
                  // 基准线
                  textBaseline: 'middle',
                  offsetY: -30,
                  // 文字样式
                  font: 'normal 16px 黑体',
                  // 文本内容
                  text: deviceInfo.title,
                  // 文本填充样式
                  fill: new Fill({
                    color: 'rgba(255,255,255,1)'
                  }),
                  padding: [5, 5, 5, 5],
                  backgroundFill: new Fill({
                    /*color: 'rgba(0,0,255,0.6)'*/
                    color: 'rgba(83,83,238,0.6)'
                  }),
                })

                /*
                                text: new Text({
                                  text: deviceInfo.title,
                                  fill: new Fill({
                                    color: '#fff',
                                  }),
                                }),
                */
              })
            } else {
              if (size > 10) {
                style = new Style({
                  image: new CircleStyle({
                    radius: 20,
                    stroke: new Stroke({
                      color: '#fff',
                    }),
                    fill: new Fill({
                      color: 'red',
                    }),
                  }),
                  text: new Text({
                    text: size.toString(),
                    fill: new Fill({
                      color: '#fff',
                    }),
                  }),
                });
              } else if (size > 5) {
                style = new Style({
                  image: new CircleStyle({
                    radius: 20,
                    stroke: new Stroke({
                      color: '#fff',
                    }),
                    fill: new Fill({
                      color: 'green',
                    }),
                  }),
                  text: new Text({
                    text: size.toString(),
                    fill: new Fill({
                      color: '#fff',
                    }),
                  }),
                });
              } else {
                style = new Style({
                  image: new CircleStyle({
                    radius: 20,
                    stroke: new Stroke({
                      color: '#fff',
                    }),
                    fill: new Fill({
                      color: 'blue',
                    }),
                  }),
                  text: new Text({
                    text: size.toString(),
                    fill: new Fill({
                      color: '#fff',
                    }),
                  }),
                });
              }


            }
            that.clusterStyles[id] = style;
          }

          return style;
        },
      });
      //console.log(">>>>>>>>>> Mapframe.refreshCluser: clusters=%o",this.clusters)
      this.mapObj.addLayer(this.clusters);
    },
    /**
     * 屏新地图
     */
    refreshMap(){
      this.$nextTick(() => {
        //this.$Message.info(this.$refs.map.offsetWidth.toString());
        if (!!this.mapObj ){
          this.mapObj.updateSize();
        }
        //this.genMap();
      })

    },

    /**
     * 注册地图缩放和拖动事件方法
     * 第一个参数是监听事件，第二个参数为是否开启监听拖动（true为不开启）
     * @param eventListen
     * @param notListenMove
     */
    registerOnZoom(eventListen, notListenMove) {
      /*      // 记录地图缩放，用于判断拖动
            this.mapObj.lastZoom = this.mapObj.lastZoom || this.mapObj.getView().getZoom();
            const that=this;
            // 地图缩放事件
            let registerOnZoom = function (e) {
              // 不监听地图拖动事件
              if (notListenMove) {
                if (that.mapObj.lastZoom != that.mapObj.getView().getZoom()) {
                  eventListen && eventListen(e);
                }
              } else {
                eventListen && eventListen(e);
              }
              that.mapObj.lastZoom = that.mapObj.getView().getZoom();
            }

            // 保存缩放和拖动事件对象，用于后期移除
            let registerOnZoomArr = that.mapObj.get('registerOnZoom') || [];

            registerOnZoomArr.push(registerOnZoom);

            // 使用地图 set 方法保存事件对象
            that.mapObj.set('registerOnZoom', registerOnZoomArr);

            // 监听地图移动结束事件
            that.mapObj.on('moveend', registerOnZoom);

            return eventListen;*/
    },


    // 关闭缩放
    /*
        closeZoom() {
          this.removeZoomRegister()
        },
    */

    /**
     * 移除缩放和拖动事件对象
     */
    removeZoomRegister(){
      /*
            let registerOnZoomArr = this.mapObj.get('registerOnZoom');
            if (registerOnZoomArr && registerOnZoomArr.length > 0) {
              for (let i = 0; i < registerOnZoomArr.length; i++) {
                this.mapObj.un('moveend', registerOnZoomArr[i]);
              }
            }
      */
    },

    /**
     * 显示设备在地图上的点
     */
    showPointer(deviceDatalist){
      for(let l in this.devicesPoints){
        this.customLayers.sourceVector.removeFeature(this.devicesPoints[l]);
      }
      this.devicesPoints = [];

      for(let i in deviceDatalist){
        this.drawOnePoint(deviceDatalist[i]);
      }
    },



    /**
     * 点击切换地图和地图类型的菜单
     */

    /**
     * 移到某中心点
     *  @param pos[lon,lat] 如： [114.236262, 22.677236]
     */

    tocenter(pos) {
      const centerPoint = !!pos?pos:this.mapInfo.center;
      let centerPoint1={lat:centerPoint[1],lon:centerPoint[0]};
/*      if (this.mapInfo.coordinateType == 'GCJ02'){
        //谷歌高德
        centerPoint1 = new GPS().gps84ToGcj02(parseFloat(centerPoint[1]), parseFloat(centerPoint[0]));
      }else if (this.mapInfo.coordinateType == 'BD09') {
        //百度
        centerPoint1 = new GPS().gps84ToBd09(centerPoint[1], centerPoint[0]);
      }//WGS84 和其它 不变*/

      this.mapObj.getView().setCenter([centerPoint1.lon,centerPoint1.lat]);

/*      let point2 = new Feature({
        geometry: new Point(posBd09),
        device:{lng:pos[0],lat:pos[1]}
      });
      point2.setStyle(pointStyle('BD09:'+pos[0]+","+pos[1]));
      this.customLayers.sourceVector.addFeature(point2);
      this.points.push(point2);*/
    },
    /**
     *放大
     */
    zoomin() {
      //console.log(">>>>>>>> Mapframe.zoomin: maxZoom=%o,zoom=%o",this.mapInfo.maxZoom,this.mapObj.getView().getZoom())
      if (this.iszooming){return ;}
      let zoom = this.mapObj.getView().getZoom();
      if (zoom < this.mapInfo.maxZoom) {
        zoom++;
      }else{
        return false;
      }
      this.iszooming=true;
      this.mapObj.getView().setZoom(zoom);
      return true;
    },
    /**
     *缩小
     */
    zoomout() {
      let zoom = this.mapObj.getView().getZoom();
      if (!!this.currentItem) {
        if (this.currentItem.minZoom <= zoom - 1) {
          zoom--;
        }
      } else if (zoom > 3) {
        zoom--;
      }
      this.mapObj.getView().setZoom(zoom)
    },
    /**
     * 开始监听地图缩放
     */
  }
}
</script>
<style lang="less">
@import "../../template";
.map-frame-main{
  width: 100%;
  height: 100%;
}
#map {
  width: 100%;
  height: 100%;
  margin: 0;
}

/**气泡 */
.bubble{
  //基本的方框
  position:relative;
  padding: 15px;
  margin: 1em 0em 3em;
  width: 300px;
  line-height: 1.2;
  text-align: center;
  color: #fff;
  background: #075698;
  //生成圆角
  -moz-border-radius: 10px;
  -webkit-border-radius: 10px;
  border-radius: 10px;
  //制作线性渐变的效果
  background: -webkit-gradient(linear, left top, left bottom, from(#f9d835), to(#f3961c));
  background: -moz-linear-gradient(to top, #f9d835, #f3961c);
  background: -o-linear-gradient(to top, #f9d835, #f3961c);
  background: linear-gradient(to top, #f9d835, #f3961c);
}
//在容器后面添加一个空元素，并将长度和宽度都设为0
.bubble:after{
  content:"\00a0";
  width:0;
  height:0;
}
//指定这个空元素为块级元素，并且四个边框之中，只显示上方的边框，其他三个边框，都设为透明。因为该元素的大小为0，所以它的每一个边框，都是一个等腰三角形
.bubble:after{
  display:block;
  border-style:solid;
  border-width:15px;
  border-color:#f3961c transparent transparent transparent;
}

//指定空元素的定位方式为absolute。然后，以容器元素的左下角为基点，将空元素水平右移一定的距离（这里是50像素），再垂直下移两个边界的距离。（由于第五步将空元素的边界设为15像素，所以这里就是下移30像素。）
/*
.bubble:after{
  position:absolute;
  z-index:-1;
  bottom:-30px;
  left:50px;
}
*/

/*右弹框*/
.mf-right-div {
  top: 200px;
  height: 140px;
  position: fixed;
  right: 20px;
  z-index: 15;
  //border-color: #e30c0c transparent transparent transparent;
  //background-color: rgb(25, 131, 239);
}

/*框选设备弹框*/
/*.devices-select-div {
  top: 130px;
  height: 140px;
  position: fixed;
  right: 20px;
  z-index: 15;
  //border-color: #e30c0c transparent transparent transparent;
  //background-color: rgb(25, 131, 239);
}*/

.test-tool-bar-draw {
  top: 300px;
  height: 140px;
  position: fixed;
  right: 20px;
  z-index: 15;
  border-color: #e30c0c transparent transparent transparent;
  background-color: rgb(100, 234, 212);
}
</style>
